package com.fabric.contract;

import com.alibaba.fastjson.JSON;
import com.fabric.contract.BussinessContractDTO;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.StringUtils;
import org.hyperledger.fabric.gateway.Contract;
import org.hyperledger.fabric.gateway.ContractException;
import org.hyperledger.fabric.gateway.Gateway;
import org.hyperledger.fabric.gateway.Network;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.concurrent.TimeoutException;


@RestController
@RequestMapping("/BussinessContractFabric")
@Slf4j
@AllArgsConstructor
public class BussinessContractController {

    final Gateway gateway;

    @GetMapping("/{contractId}")
    public Map<String, Object> queryContractById(@PathVariable String contractId) throws ContractException {
        Map<String, Object> result = Maps.newConcurrentMap();
        Contract contract = getContract();
        byte[] contractData = contract.evaluateTransaction("queryContract", contractId);

        result.put("payload", StringUtils.newStringUtf8(contractData));
        result.put("status", "ok");

        return result;
    }

    @PostMapping("/create")
    public Map<String, Object> createContract(@RequestBody BussinessContractDTO contract) throws InterruptedException, TimeoutException, ContractException {
        Map<String, Object> result = Maps.newConcurrentMap();
        Contract contractInstance = getContract();

        byte[] bytes = contractInstance.submitTransaction("createContract", JSON.toJSONString(contract));

        result.put("payload", StringUtils.newStringUtf8(bytes));
        result.put("status", "ok");
        return result;
    }

    @PostMapping("/update")
    public Map<String, Object> updateContract(@RequestBody BussinessContractDTO contract) throws InterruptedException, TimeoutException, ContractException {
        Map<String, Object> result = Maps.newConcurrentMap();
        Contract contractInstance = getContract();
        byte[] bytes = contractInstance.submitTransaction("updateContract", JSON.toJSONString(contract));

        result.put("payload", StringUtils.newStringUtf8(bytes));
        result.put("status", "ok");

        return result;
    }

    @DeleteMapping("/delete/{contractId}")
    public Map<String, Object> deleteContract(@PathVariable String contractId) throws InterruptedException, TimeoutException, ContractException {
        Map<String, Object> result = Maps.newConcurrentMap();
        Contract contractInstance = getContract();

        byte[] bytes = contractInstance.submitTransaction("deleteContract", contractId);

        result.put("payload", StringUtils.newStringUtf8(bytes));
        result.put("status", "ok");

        return result;
    }

    @GetMapping("/owner/{owner}/type/{contractType}")
    public Map<String, Object> queryContractByOwnerAndType(@PathVariable String owner, @PathVariable String contractType) throws ContractException {
        Map<String, Object> result = Maps.newConcurrentMap();
        Contract contract = getContract();
        byte[] contracts = contract.evaluateTransaction("queryContractByOwnerAndType", owner, contractType);

        result.put("payload", StringUtils.newStringUtf8(contracts));
        result.put("status", "ok");

        return result;
    }

    private Network getNetwork() {
        // 获取通道
        return gateway.getNetwork("mychannel");
    }

    private Contract getContract() {
        // 获取合约
        return getNetwork().getContract("contract_chaincode");
    }
}
